package org.example.optimistic.lock.ATM;

import lombok.AllArgsConstructor;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author zhengdp
 * @Description  取款操作测试（线程不安全 & 线程安全）
 * @Date 2022/11/19 15:48
 * @Created by zhengdp
 */
public class TestAccount {
    public static void main(String[] args) {
        System.out.println("Unsafe : ");
        Account account = new AccountUnsafe(10000);
        Account.demo(account);
        System.out.println("====================");
        Account account1 = new AccountSafe(10000);
        Account.demo(account1);
    }
}


class AccountSafe implements Account {

    private AtomicInteger balance;

    public AccountSafe(int balance) {
        this.balance = new AtomicInteger(balance);
    }

    @Override
    public Integer getBalance() {
        return this.balance.get();
    }

    @Override
    public void withdraw(Integer amount) {
        while(true) {
            // 获取余额的最新值
            int prev = balance.get();
            // 要修改的余额
            int next = prev - amount;
            // 将要修改的余额 同步到 主存中 （比较后设置）
            if(balance.compareAndSet(prev,next)) {
                break;
            }
        }
    }
}

@AllArgsConstructor
class AccountUnsafe implements Account {

    private Integer balance;
    @Override
    public Integer getBalance() {
        return this.balance;
    }

    /**
     * 临界区代码，但是任何的线程同步控制，肯定会造成线程安全问题
     * @param amount 取款金额
     */
    @Override
    public void withdraw(Integer amount) {
        synchronized (this) {
            this.balance -= amount;
        }
    }
}
